#include <stdio.h>
#include <getopt.h>

/*
 * binary_view.c
 *
 * this program shows the binary data.
 *
 * required csv file format
 *   tag,from,to
 *   tag,from,to
 *   tag,from,to
 *   .
 *   .
 *
 */

#define BUF_SIZE 1024

#define NO_DISPLAY_HEX 1
#define DISPLAY_CHAR   2
#define PARAM_IS_HEX   4

void usage( char **argv ) {

  printf( "usage : %s [options] <csv file> <input binary file>\n", argv[ 0 ] ) ;
  printf( "\n" ) ;
  printf( "[options]\n" ) ;
  printf( "  -h : show this message and exit.\n" ) ;
  printf( "  -n : not display hex.\n" ) ;
  printf( "  -s : display characters.\n" ) ;
  printf( "  -x : the parameters in csv are hex.\n" ) ;
  return ;

}

void display_data( int c, unsigned int flag ) {

  if( ! ( flag & NO_DISPLAY_HEX ) )
    printf( " %02X", c ) ;

  if( ! ( flag & DISPLAY_CHAR ) )
    return ;

  if( c > 32 && c < 127 ) {
    printf( " %c", c ) ;
  } else {
    printf( " ." ) ;
  }

}

unsigned int next_param( unsigned int flag, FILE *fp, char *tag, int *from, int *to ) {

  if( flag & PARAM_IS_HEX )
    return fscanf( fp, "%[^,],%x,%x\n", tag, from, to ) == EOF ? 0 : 1 ;

  return fscanf( fp, "%[^,],%d,%d\n", tag, from, to ) == EOF ? 0 : 1 ;

}

int main( int argc, char **argv ) {

  FILE *fcsv, *fin ;
  int c, opt, from, to ;
  char tag[ BUF_SIZE ] ;
  unsigned int i = 0, opt_count = 0, flag = 0, has_next = 0 ;

  while( ( opt = getopt( argc, argv, "hnsx" ) ) != -1 ) {
    switch( opt ) {
      case 'h' :
        usage( argv ) ;
        return 0 ;
      case 'n' :
        flag |= NO_DISPLAY_HEX | DISPLAY_CHAR ;
        opt_count++ ;
        break ;
      case 's' :
        flag |= DISPLAY_CHAR ;
        opt_count++ ;
        break ;
      case 'x' :
       flag |= PARAM_IS_HEX ;
        opt_count++ ;
        break ;
      default :
        usage( argv ) ;
        return -1 ;
    }
  }

  if( argc - opt_count != 3 ) {
    usage( argv ) ;
    return -1 ;
  }

  if( ! ( fcsv = fopen( argv[ optind + 0 ], "r" ) ) ) {
    printf( "failed to open csv file.\n" ) ;
    return -1 ;
  }

  if( ! ( fin = fopen( argv[ optind + 1 ], "rb" ) ) ) {
    printf( "failed to open input file.\n" ) ;
    fclose( fcsv ) ;
    return -1 ;
  }

  has_next = next_param( flag, fcsv, tag, &from, &to ) ;
  while( ( c = getc( fin ) ) != EOF ) {
    if( ! has_next ) {
      break ;
    } else if( from == to && i == from ) {
      printf( "%-10s :", tag ) ;
      display_data( c, flag ) ;
      printf( "\n" ) ;
      has_next = next_param( flag, fcsv, tag, &from, &to ) ;
    } else if( from < to && i >= from && i <= to ) {
      if( i == from )
        printf( "%-10s :", tag ) ;
      display_data( c, flag ) ;
      if( i == to ) {
        printf( "\n" ) ;
        has_next = next_param( flag, fcsv, tag, &from, &to ) ;
      }
    } else {

    }
    i++ ;
  }

  fclose( fin ) ;
  fclose( fcsv ) ;

  return 0 ;

}

